#ifndef __NEZHA_MEMORY_H__
#define __NEZHA_MEMORY_H__

#include "NezhaAllocator.h"

// TODO aligned alloc

#ifdef USE_ALLOCATOR
#		ifdef MEMORY_LEAK_CHECK

#			define NZ_New new(__FILE__, __LINE__)
#			define NZMalloc(bytes) NZ_Malloc(bytes, __FILE__, __LINE__)
#			define NZRealloc(prev, bytes) NZ_Realloc(prev, bytes, __FILE__, __LINE__)
#			define NZFree NZ_Free

			inline void* NZ_Malloc(size_t bytes, const char* fileName, int line)
			{
				void* p = NZAllocator::GetInstance()->malloc(bytes);
				NZMemoryTrack::GetInstance()->push(p, bytes, fileName, line);
				return p;
			}

			inline void* NZ_Realloc(void* prev, size_t bytes, const char* fileName, int line)
			{
				void* p = NZAllocator::GetInstance()->realloc(prev, bytes);
				NZMemoryTrack::GetInstance()->pop(prev);
				NZMemoryTrack::GetInstance()->push(p, bytes, fileName, line);
				return p;
			}

			inline void NZ_Free(void* p)
			{
				NZMemoryTrack::GetInstance()->pop(p);
				NZAllocator::GetInstance()->free(p);
			}

			inline void* operator new(size_t bytes, const char* fileName, int line)
			{
				void* p = NZAllocator::GetInstance()->malloc(bytes);
				NZMemoryTrack::GetInstance()->push(p, bytes, fileName, line);
				return p;
			}

			inline void* operator new[](size_t bytes, const char* fileName, int line)
			{
				void* p = NZAllocator::GetInstance()->malloc(bytes);
				NZMemoryTrack::GetInstance()->popArray(p, bytes, fileName, line);
				return p;
			}

			inline void operator delete(void* p)
			{
				NZMemoryTrack::GetInstance()->pop(p);
				NZAllocator::GetInstance()->free(p);
			}

			inline void operator delete[](void * p)
			{
				NZMemoryTrack::GetInstance()->popArray(p);
				NZAllocator::GetInstance()->free(p);
			}

			// for memory exception handle
			inline void operator delete(void* p, const char* fileName, int line)
			{
				NZAllocator::GetInstance()->free(p);
			}

			inline void operator delete[](void* p, const char* fileName, int line)
			{
				NZAllocator::GetInstance()->free(p);
			}

#		else

#			define NZ_New new
#			define NZMalloc(bytes) NZAllocator::GetInstance()->malloc(bytes)
#			define NZRealloc(prev, bytes) NZAllocator::GetInstance()->realloc(prev, bytes)
#			define NZFree NZ_Free NZAllocator::GetInstance()->free

			inline void operator new(size_t bytes)
			{
				return NZAllocator::GetInstance()->malloc(bytes);
			}

			inline void operator new[] (size_t bytes)
			{
				return NZAllocator::GetInstance()->malloc(bytes);
			}

			inline void operator delete(void* p)
			{
				NZAllocator::GetInstance()->free(p);
			}

			inline void operator delete[](void * p)
			{
				NZAllocator::GetInstance()->free(p);
			}

#		endif

#else

#			define NZ_New new
#			define NZMalloc(bytes) malloc(bytes)
#			define NZRealloc(prev, bytes) realloc(prev, bytes)
#			define NZFree free

#endif //end USE_ALLOCATOR

#define NZ_Delete delete

//
// for system memory that would't be handled by allocator or tracker
#define SystemMalloc malloc
#define SystemRealloc realloc
#define SystemFree free

/**
* Inherting form this base class for which classes want to use system memory
* allocation & management.
*/
class  FOUNDATION_ENTRY SystemAllocated
{
public:
	inline void* operator new(size_t bytes)
	{
		return SystemMalloc(bytes);
	}

	inline void* operator new[](size_t bytes)
	{
		return SystemMalloc(bytes);
	}

	inline void operator delete(void* p)
	{
		SystemFree(p);
	}

	inline void operator delete[](void* p)
	{
		SystemFree(p);
	}
};

#endif //end __NEZHA_MEMORY_H__